import { execSync } from 'node:child_process';
import os from 'node:os';
import path from 'node:path';
import dayjs from 'dayjs';
import fs from 'fs-extra';
import xml2js from 'xml2js';

// 系统环境配置
const ENV = {
  // 操作系统类型
  platform: process.platform,
  // 是否为 Windows 系统
  isWindows: process.platform === 'win32',
  // 是否为 macOS 系统
  isMac: process.platform === 'darwin',
  // 是否为 Linux 系统
  isLinux: process.platform === 'linux'
};

// 路径配置
const UNIAPP_ROOT = path.resolve(process.env.UNIAPP_ROOT || '/d/code/healthkioskvue3');
const ANDROID_ROOT = path.resolve(process.env.ANDROID_ROOT || '/d/code/healthkioskvue3/androidplugingroup');

// 检查项目是否存在
async function checkProjectExists() {
  if (!(await fs.pathExists(UNIAPP_ROOT))) {
    throw new Error(`UniApp 项目不存在：${UNIAPP_ROOT}`);
  }
  if (!(await fs.pathExists(ANDROID_ROOT))) {
    throw new Error(`Android 项目不存在：${ANDROID_ROOT}`);
  }
}

// 路径配置
const PATHS = {
  // UniApp 项目路径
  uniapp: {
    // 项目根目录
    root: UNIAPP_ROOT,
    // 构建输出目录
    get dist() { return path.join(this.root, 'dist', 'build', 'app'); },
    // manifest.json 路径
    get manifest() { return path.join(this.root, 'src', 'manifest.json'); },
    // APK 输出目录
    get apkOutputDir() { return path.join(this.root, 'dist', 'release'); }
  },

  // Android 项目路径
  android: {
    // 项目根目录
    root: ANDROID_ROOT,
    // assets 目录
    get assets() { return path.join(this.root, 'app', 'src', 'main', 'assets', 'apps'); },
    // strings.xml 路径
    get stringsXml() { return path.join(this.root, 'app', 'src', 'main', 'res', 'values', 'strings.xml'); },
    // APK 输出路径
    get apkOutput() { return path.join(this.root, 'app', 'build', 'outputs', 'apk', 'release', 'app-release.apk'); }
  }
};

/**
 * 执行命令并显示输出
 * @param {string} command - 要执行的命令
 * @param {string} cwd - 工作目录
 */
function runCommand(command, cwd) {
  console.log(`执行命令: ${command}`);
  execSync(command, { stdio: 'inherit', cwd });
}

/**
 * 修改 Android strings.xml 中的应用名称
 * @param {string} appName - 新的应用名称
 */
async function modifyAppNameInStringsXml(appName) {
  const stringsXmlPath = PATHS.android.stringsXml;

  if (!await fs.pathExists(stringsXmlPath)) {
    throw new Error(`strings.xml 文件不存在：${stringsXmlPath}`);
  }

  const xmlContent = await fs.readFile(stringsXmlPath, 'utf-8');
  const parser = new xml2js.Parser();
  const builder = new xml2js.Builder();

  const xmlObj = await parser.parseStringPromise(xmlContent);

  if (!xmlObj.resources || !xmlObj.resources.string) {
    throw new Error('strings.xml 文件格式异常，缺少 <resources><string> 节点');
  }

  // 查找并更新或添加 app_name 条目
  let found = false;
  for (const strNode of xmlObj.resources.string) {
    if (strNode.$.name === 'app_name') {
      strNode._ = appName;
      found = true;
      break;
    }
  }

  if (!found) {
    xmlObj.resources.string.push({
      _: appName,
      $: { name: 'app_name' }
    });
  }

  const newXml = builder.buildObject(xmlObj);
  await fs.writeFile(stringsXmlPath, newXml, 'utf-8');
  console.log(`✔ 已更新安卓项目 strings.xml 中的 app_name 为 "${appName}"`);
}

/**
 * 从 manifest.json 读取应用信息
 * @returns {object} 包含 name 和 appId 的应用信息
 */
async function readAppInfo() {
  const manifestPath = PATHS.uniapp.manifest;

  if (!await fs.pathExists(manifestPath)) {
    throw new Error('manifest.json 不存在，请检查路径');
  }

  const manifest = await fs.readJson(manifestPath);
  return {
    name: manifest.name || 'app-release',
    appId: manifest.appid
  };
}

/**
 * 步骤 1: 构建 UniApp 项目
 */
async function buildUniApp() {
  console.log('1. 执行 uniapp 构建：npm run build:app');
  runCommand('npm run build:app', PATHS.uniapp.root);
}

/**
 * 步骤 2: 将 UniApp 构建输出复制到 Android 项目
 * @param {string} appId - manifest 中的应用 ID
 */
async function copyToAndroidProject(appId) {
  const androidAssetsDir = path.join(PATHS.android.assets, appId, 'www');

  console.log(`2. 复制 uniapp 构建产物 ${PATHS.uniapp.dist} 到安卓项目 assets 目录 ${androidAssetsDir}`);
  await fs.remove(androidAssetsDir);
  await fs.copy(PATHS.uniapp.dist, androidAssetsDir);
}

/**
 * 获取适合当前操作系统的 Gradle 命令
 * @param {string} command - 基础命令（如 'clean' 或 'assembleRelease'）
 * @returns {string} - 适合当前操作系统的完整命令
 */
function getGradleCommand(command) {
  let gradleCmd;

  if (ENV.isWindows) {
    // Windows 使用 gradlew.bat
    gradleCmd = `gradlew.bat ${command}`;
  }
  else {
    // macOS 和 Linux 使用 ./gradlew
    gradleCmd = `./gradlew ${command}`;

    // 确保 gradlew 有执行权限
    const gradlewPath = path.join(PATHS.android.root, 'gradlew');
    if (fs.existsSync(gradlewPath)) {
      try {
        fs.chmodSync(gradlewPath, '755');
      }
      catch (error) {
        console.warn('警告: 无法修改 gradlew 权限:', error.message);
      }
    }
  }

  return gradleCmd;
}

/**
 * 步骤 3: 构建 Android APK
 */
async function buildAndroidApk() {
  console.log('3. 运行安卓项目 gradlew clean');
  const cleanCmd = getGradleCommand('clean');
  runCommand(cleanCmd, PATHS.android.root);

  console.log('4. 运行安卓项目 gradlew assembleRelease');
  const buildCmd = getGradleCommand('assembleRelease');
  runCommand(buildCmd, PATHS.android.root);
}

/**
 * 步骤 4: 将 APK 复制回 UniApp 项目并添加时间戳
 * @param {string} appName - 用于 APK 文件名的应用名称
 * @returns {Promise<string>} - 生成的 APK 路径
 */
async function copyApkToOutput(appName) {
  const apkSrc = PATHS.android.apkOutput;

  if (!await fs.pathExists(apkSrc)) {
    throw new Error('APK 文件不存在，请确认 assembleRelease 是否成功');
  }

  await fs.ensureDir(PATHS.uniapp.apkOutputDir);
  const timestamp = dayjs().format('YYYYMMDDHHmmss');
  const apkDst = path.join(PATHS.uniapp.apkOutputDir, `${appName}${timestamp}.apk`);

  await fs.copy(apkSrc, apkDst);
  return apkDst;
}

async function main() {
  try {
    // 显示环境信息
    console.log(`运行环境: ${ENV.platform} (${os.type()} ${os.release()})`);

    console.log('>>>process', process.env);

    await checkProjectExists();

    // 步骤 1: 构建 UniApp 项目
    await buildUniApp();

    // 步骤 2: 读取应用信息
    console.log('2. 读取 uniapp 应用信息: ', PATHS.uniapp.manifest);
    const { name: appName, appId } = await readAppInfo();

    // 步骤 3: 复制到 Android 项目
    await copyToAndroidProject(appId);

    // 步骤 4: 更新 Android 应用名称
    console.log('4. 修改安卓项目 strings.xml 中的 app_name');
    await modifyAppNameInStringsXml(appName);

    // 步骤 5: 构建 Android APK
    await buildAndroidApk();

    // 步骤 6: 将 APK 复制到输出目录
    console.log(`5. 复制 APK 到 uniapp 项目并重命名为 ${appName}.apk`);
    const apkPath = await copyApkToOutput(appName);

    console.log(`🎉 构建完成，APK 文件位于: ${apkPath}`);
  }
  catch (err) {
    console.error('构建失败:', err);
    process.exit(1);
  }
}

// 启动构建流程
main();
